package com.cff.springbootwork.mail.service;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.cff.springbootwork.mail.type.*;

@Service
public class MailService {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	static final String DELIM_STR = "{}";

	@Autowired
	private JavaMailSender javaMailSender;
	
	@Value("${mail.from}")
	private String from;
	
	@Value("${mail.fromName}")
	private String fromName;
	
	/**
	 * 简单发送html内容
	 * 
	 * @param to
	 *            指定收件人
	 * @param subject
	 *            主题
	 * @param content
	 *            内容
	 * @param isHtml
	 *            是否是html
	 */
	public void sendSimpleMail(String to, String subject, String content, boolean isHtml) {
		MimeMessage message = javaMailSender.createMimeMessage();
		try {
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(from,fromName);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, isHtml);
			javaMailSender.send(message);
			logger.info("html邮件发送成功");
		} catch (MessagingException e) {
			logger.error("发送html邮件时发生异常！", e);
		} catch (UnsupportedEncodingException e) {
			logger.error("发送html邮件时发生异常！", e);
		}

	}

	/**
	 * 简单发送内嵌文件方法
	 * 
	 * @param to
	 *            指定收件人
	 * @param subject
	 *            主题
	 * @param content
	 *            内容
	 * @param rscPath
	 *            资源路径（文件路径）
	 * @param rscId
	 *            资源标识
	 */
	public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId) {
		MimeMessage message = javaMailSender.createMimeMessage();

		try {
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(from,fromName);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, true);

			FileSystemResource res = new FileSystemResource(new File(rscPath));
			helper.addInline(rscId, res);

			javaMailSender.send(message);
			logger.info("嵌入静态资源的邮件已经发送。");
		} catch (MessagingException e) {
			logger.error("发送嵌入静态资源的邮件时发生异常！", e);
		} catch (UnsupportedEncodingException e) {
			logger.error("发送嵌入静态资源的邮件时发生异常！", e);
		}
	}

	/**
	 * 简单发送附件方法
	 * 
	 * @param to
	 *            指定收件人
	 * @param subject
	 *            主题
	 * @param content
	 *            内容
	 * @param filePath
	 *            附件地址，可传递多个
	 */
	public void sendAttachmentsMail(String to, String subject, String content, String[] filePaths) {
		System.getProperties().setProperty("mail.mime.splitlongparameters", "false");

		MimeMessage message = javaMailSender.createMimeMessage();
		try {
			MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
			helper.setFrom(from,fromName);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, true);

			for (String filePath : filePaths) {
				FileSystemResource file = new FileSystemResource(new File(filePath));
				String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
				helper.addAttachment(MimeUtility.encodeText(fileName), file);
			}

			javaMailSender.send(message);
			logger.info("带附件的邮件已经发送。");
		} catch (MessagingException e) {
			logger.error("发送带附件的邮件时发生异常！", e);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 完整发送邮件方法，需要调用setMailMessage方法配置邮件 {@link #setMailMessage(MailMessage)}
	 * <p>占位符使用{},内容中如果要使用{},就修改代码吧，这里不支持。
	 * @param content
	 *            带占位符正文
	 * @param mailTypes
	 *            可变参数，填充占位符
	 * @throws Exception 
	 */
	public void sendCompleteHtml(String content, List<MailType> mailTypes, MailMessage mailMessage) throws Exception {
		System.getProperties().setProperty("mail.mime.splitlongparameters", "false");
		if (mailMessage.getFrom() == null || "".equals(mailMessage.getFrom())) {
			mailMessage.setFrom(from);
			mailMessage.setFromName(fromName);
		}
		MimeMessage message = javaMailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setFrom(mailMessage.getFrom());
		helper.setTo(mailMessage.getTo());
		if (mailMessage.getCc() != null && mailMessage.getCc().length > 0)
			helper.setCc(mailMessage.getCc());
		helper.setSubject(mailMessage.getSubject());
		String msg = getContent(content, mailTypes);
		helper.setText(msg, true);
		for (MailType item : mailTypes) {
			switch (item.getType()) {
			case MailType.TYPE_FILE:
				if (item != null) {
					InlineFile inlineFile = (InlineFile) item;
					helper.addInline(inlineFile.getCid(), new File(inlineFile.getFilePath()));
				}
				break;
			case MailType.TYPE_ATTACH:
				if (item != null) {
					AttachFile attachFile = (AttachFile) item;
					helper.addAttachment(MimeUtility.encodeText(attachFile.getFileName()),
							new File(attachFile.getFilePath()));
				}
				break;
			}
		}
		try{
			javaMailSender.send(message);
		}catch(MailException e){
			logger.error("邮件发送过程出错，重发一次。",e);
			javaMailSender.send(message);
		}
		logger.info("完整的邮件已经发送。");

	}

	/**
	 * 解析占位符
	 *
	 * @param content
	 *            字符串，带占位符{},有多少个{},就要有多少个MailType
	 * @param mailTypes
	 *            MailType填充参数, 注：换行需主动添加
	 * @return 解析后的正文
	 * @throws MessagingException
	 * @throws IOException
	 */
	private String getContent(String content, List<MailType> mailTypes) throws MessagingException, IOException {
		String bodyPrefix = "<html><body>";
		String bodySuffix = "</body></html>";
		StringBuffer sb = new StringBuffer();
		sb.append(bodyPrefix);
		for (MailType item : mailTypes) {
			if (content.length() < 1)
				break;

			int index = content.indexOf(DELIM_STR);
			if (index == -1)
				break;
			sb.append(content.substring(0, index));
			switch (item.getType()) {
			case MailType.TYPE_FILE:
				if (item != null) {
					InlineFile inlineFile = (InlineFile) item;
					sb.append("<img src=\'cid:" + inlineFile.getCid() + "\' />");
				}
				break;
			case MailType.TYPE_TEXT:
				TextString textString = (TextString) item;
				sb.append(textString.getText());
				break;
			case MailType.TYPE_JSON:
				JsonTable json = (JsonTable) item;
				sb.append(genReportData(json));
				
				break;
			}
			content = content.substring(index + 2);
		}
		sb.append(content);
		sb.append(bodySuffix);
		return sb.toString();
	}

	/**
	 * 根据Json字符串，生成有序的表格
	 *
	 * @param jsonTable
	 *            json转table实体
	 * @return 表格字符串
	 * @throws IOException
	 */
	private String genReportData(JsonTable jsonTable) throws IOException {
		JSONArray ja = (JSONArray) JSON.parse(jsonTable.getData(), Feature.OrderedField);
		StringBuilder sb = new StringBuilder();
		try {
			sb.append("<table border=\"1\" style=\"border-collapse:collapse;font-size:14px\">\n");
			sb.append("<caption align = \"left\">");
			sb.append(jsonTable.getTitle());
			sb.append("</caption>\n");
			JSONObject jsonFirst = (JSONObject) ja.get(0);
			sb.append("<tr>\n");
			for (String key : jsonFirst.keySet()) {
				sb.append("<td>");
				sb.append(jsonFirst.get(key));
				sb.append("</td>\n");
			}

			sb.append("</tr>\n");
			ja.remove(0);
			for (Object column : ja) {
				sb.append("<tr>\n");
				JSONObject json = (JSONObject) column;
				for (String key : jsonFirst.keySet()) {
					sb.append("<td>");
					sb.append(json.get(key));
					sb.append("</td>\n");
				}

				sb.append("</tr>\n");
			}

			sb.append("</table>\n");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	public String getFrom() {
		return from;
	}

	public void setFrom(String from) {
		this.from = from;
	}

	public JavaMailSender getJavaMailSender() {
		return javaMailSender;
	}

	public void setJavaMailSender(JavaMailSender javaMailSender) {
		this.javaMailSender = javaMailSender;
	}

	public String getFromName() {
		return fromName;
	}

	public void setFromName(String fromName) {
		this.fromName = fromName;
	}
}
